#include "LGrammar.h"
#include <iostream>

LGrammar::LGrammar() { }

LGrammar::LGrammar(const LGrammar &rhs)
	:	startString(rhs.startString),
		rules(rhs.rules) {
	curString = startString;
	curIndex = 0;
	depth = rhs.depth;
}

LGrammar& LGrammar::operator=(const LGrammar &rhs) {
	startString = rhs.startString;
	rules = std::vector<LGrammarRule*>(rhs.rules);
	curString = startString;
	curIndex = 0;
	depth = rhs.depth;
	return *this;
}

LGrammar::~LGrammar() {
	std::vector<LGrammarRule*>::iterator it = rules.begin();
	while(it != rules.end()) {
		delete (*(it++));
	}
}

void LGrammar::setStartString(std::string start){
	startString = start;
	curString = start;
	curIndex = 0;
}

void LGrammar::addRule(LGrammarRule *rule) {
	rules.push_back(rule);
}

void LGrammar::setDepth(int d) {
	depth = d;
}

void LGrammar::reset(void) {
	while(!strStack.empty()) {
		strStack.pop();
	}
	while(!indexStack.empty()) {
		indexStack.empty();
	}
	curIndex = 0;
	curString = startString;
}

std::string LGrammar::getStartString(void) {
	return startString;
}

std::string LGrammar::getRule(char nonTerminal) {
	for(int i = 0; i < rules.size(); i++) {
		if( rules[i]->getNonTerminal() == nonTerminal ) {
			return rules[i]->getProduction();
		}
	}
	return "";
};

char LGrammar::getNextChar(void) {
	while(curIndex >= curString.length()) {
		if(strStack.empty() || indexStack.empty()) {
			return 0;
		}
		curIndex = indexStack.top();
		curString = strStack.top();
		indexStack.pop();
		strStack.pop();
		depth++;
	}
	char next = curString[curIndex];
	std::string production = getRule(next);
	curIndex++;
	if(production.length() <= 0 || depth <= 0) {
		return next;
	}
	indexStack.push(curIndex);
	curIndex = 0;
	strStack.push(curString);
	curString = production;
	depth--;
	return getNextChar();
}

/*
int main(int argc, char** argv) {
	LGrammarRule a('a', "aac", 1);
	a.addProductionRule("ab", 1);
	a.addProductionRule("b", 1);

	LGrammarRule c('c', "l");
	
	LGrammar grammar = LGrammar();
	grammar.setStartString("ac");
	grammar.addRule(&a);
	grammar.addRule(&c);
	grammar.setDepth(3);

	char nextChar = grammar.getNextChar();
	while(nextChar > 0) {
		std::cout << nextChar;
		nextChar = grammar.getNextChar();
	}
	int i;
	std::cin >> i;
	

	return 0;
}
*/